package bbs.utils;


import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.util.Date;
import java.util.Objects;

/**
 * 关于日期的工具类 （ 包含JDK1.8 之后的内容）
 *
 * @author ljg;
 * @create 2022-06-08 10:01
 */
public class DateUtils {

    /**
     * java.util.Date 转成 java.time.ZonedDateTime
     */
    public static ZonedDateTime dateToZonedDateTime(Date date) {
        Instant instant = date.toInstant();
        return ZonedDateTime.ofInstant(instant, ZoneOffset.systemDefault());
    }

    /**
     * java.util.Date 转成 java.time.OffsetDateTime
     */
    public static OffsetDateTime dateToOffsetDateTime(Date date) {
        Instant instant = date.toInstant();
        return OffsetDateTime.ofInstant(instant, ZoneOffset.systemDefault());
    }

    /**
     * java.util.Date 转成 java.time.LocalDateTime
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        return LocalDateTime.ofInstant(instant, ZoneOffset.systemDefault());
    }

    /**
     * java.util.Date 转成 java.time.LocalTime
     */
    public static LocalTime dateToLocalTime(Date date) {
        Instant instant = date.toInstant();
        return LocalTime.ofInstant(instant, ZoneOffset.systemDefault());
    }

    /**
     * java.util.Date 转成 java.time.LocalDate
     */
    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        return LocalDate.ofInstant(instant, ZoneOffset.systemDefault());
    }

    /**
     * java.util.Date 转成 java.time.OffsetTime
     */
    public static OffsetTime dateToOffsetTime(Date date) {
        Instant instant = date.toInstant();
        return OffsetTime.ofInstant(instant, ZoneOffset.systemDefault());
    }

    /**
     * java.time.ZonedDateTime 转成 java.util.Date
     */
    public static Date getUtilDate(ZonedDateTime zonedDateTime) {
        Instant instant = zonedDateTime.toInstant();
        return Date.from(instant);
    }

    /**
     * java.time.OffsetDateTime 转成 java.util.Date
     */
    public static Date getUtilDate(OffsetDateTime offsetDateTime) {
        Instant instant = offsetDateTime.toInstant();
        return Date.from(instant);
    }

    /**
     * java.time.LocalDateTime 转成 java.util.Date
     */
    public static Date getUtilDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneOffset.systemDefault();
        ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
        return getUtilDate(zonedDateTime);
    }

    /**
     * java.time.LocalDate 转成 java.util.Date
     */
    public static Date getUtilDate(LocalDate localDate) {
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneOffset.systemDefault());
        return getUtilDate(zonedDateTime);
    }

    /**
     * java.time.ZonedDateTime 转成 java.sql.Date
     */
    public static java.sql.Date getSQLDate(ZonedDateTime zonedDateTime) {
        Instant instant = zonedDateTime.toInstant();
        Date from = Date.from(instant);
        return new java.sql.Date(from.getTime());
    }

    /**
     * java.time.OffsetDateTime 转成 java.sql.Date
     */
    public static java.sql.Date getSQLDate(OffsetDateTime offsetDateTime) {
        Instant instant = offsetDateTime.toInstant();
        Date from = Date.from(instant);
        return new java.sql.Date(from.getTime());
    }

    /**
     * java.time.LocalDateTime 转成 java.sql.Date
     */
    public static java.sql.Date getSQLDate(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneOffset.systemDefault();
        ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
        return getSQLDate(zonedDateTime);
    }

    /**
     * java.time.LocalDate 转成 java.sql.Date
     */
    public static java.sql.Date getSQLDate(LocalDate localDate) {
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneOffset.systemDefault());
        return getSQLDate(zonedDateTime);
    }

    /**
     * java.time.ZonedDateTime 转成 java.sql.Timestamp
     */
    public static java.sql.Timestamp getTimestamp(ZonedDateTime zonedDateTime) {
        Instant instant = zonedDateTime.toInstant();
        Date from = Date.from(instant);
        return new java.sql.Timestamp(from.getTime());
    }

    /**
     * java.time.OffsetDateTime 转成 java.sql.Timestamp
     */
    public static java.sql.Timestamp getTimestamp(OffsetDateTime offsetDateTime) {
        Instant instant = offsetDateTime.toInstant();
        Date from = Date.from(instant);
        return new java.sql.Timestamp(from.getTime());
    }

    /**
     * java.time.LocalDateTime 转成 java.sql.Timestamp
     */
    public static java.sql.Timestamp getTimestamp(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneOffset.systemDefault();
        ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
        return getTimestamp(zonedDateTime);
    }

    /**
     * 传入年月日 时分 构建 java.util.Date 类型的对象
     */
    public static Date getDate(int year, int month, int day, int hour, int minute) {
        return getDate(year, month, day, hour, minute, 0, 0);
    }

    /**
     * 传入年月日 时分秒 构建 java.util.Date 类型的对象
     */
    public static Date getDate(int year, int month, int day, int hour, int minute, int second) {
        return getDate(year, month, day, hour, minute, second, 0);
    }

    /**
     * 传入年月日 时分秒 纳秒 构建 java.util.Date 类型的对象
     */
    public static Date getDate(int year, int month, int day, int hour, int minute, int second, int nanos) {
        LocalDateTime localDateTime = LocalDateTime.of(year, month, day, hour, minute, second, nanos);
        return getUtilDate(localDateTime);
    }


    /**
     * 传入年月日 时分 构建 java.sql.Timestamp 类型的对象
     */
    public static java.sql.Timestamp getTimestamp(int year, int month, int day, int hour, int minute) {
        return getTimestamp(year, month, day, hour, minute, 0, 0);
    }

    /**
     * 传入年月日 时分秒 构建 java.sql.Timestamp 类型的对象
     */
    public static java.sql.Timestamp getTimestamp(int year, int month, int day, int hour, int minute, int second) {
        return getTimestamp(year, month, day, hour, minute, second, 0);
    }

    /**
     * 传入年月日 时分秒 纳秒 构建 java.sql.Timestamp 类型的对象
     */
    public static java.sql.Timestamp getTimestamp(int year, int month, int day, int hour, int minute, int second, int nanos) {
        LocalDateTime localDateTime = LocalDateTime.of(year, month, day, hour, minute, second, nanos);
        return getTimestamp(localDateTime);
    }

    /**
     * 传入年月日 时分 构建 String 类型的对象 , 格式为 ： yyyy-MM-dd HH:mm:ss
     */
    public static String getString(int year, int month, int day, int hour, int minute) {
        return getString(year, month, day, hour, minute, 0, 0);
    }

    /**
     * 传入年月日 时分秒 构建 String 类型的对象 , 格式为 ： yyyy-MM-dd HH:mm:ss
     */
    public static String getString(int year, int month, int day, int hour, int minute, int second) {
        return getString(year, month, day, hour, minute, second, 0);
    }

    /**
     * 传入年月日 时分秒 纳秒 构建 String 类型的对象 , 格式为 ： yyyy-MM-dd HH:mm:ss
     */
    public static String getString(int year, int month, int day, int hour, int minute, int second, int nanos) {
        LocalDateTime localDateTime = LocalDateTime.of(year, month, day, hour, minute, second, nanos);
        return format(localDateTime);
    }

    private static final String DEFAULT_ALL_PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static final String DEFAULT_DATE = "yyyy-MM-dd";
    private static final String DEFAULT_TIME = "HH:mm:ss";
    private static final DateFormat BEFORE_8_FORMAT = new SimpleDateFormat(DEFAULT_ALL_PATTERN);
    private static final DateTimeFormatter AFTER_8_FORMAT = DateTimeFormatter.ofPattern(DEFAULT_ALL_PATTERN);

    /**
     * 传入任何一个有关于 时间和日期的对象， 都可以进行格式化
     */
    public static String format(Object o) {
        if (o instanceof Date date) {
            return BEFORE_8_FORMAT.format(date);
        }
        if (o instanceof Temporal temporal) {
            return AFTER_8_FORMAT.format(temporal);
        }
        throw new DateTimeException("传入的对象不是一个时间与日期相关的对象");
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个java.util.Date 类型的对象
     */
    public static Date parseStringToUtilDate(String message) throws ParseException {
        Objects.requireNonNull(message, "传入的内容不能是null");
        DateFormat dateFormat = null;
        if (message.length() > 10) {
            return BEFORE_8_FORMAT.parse(message);
        } else if (message.contains("-")) {
            dateFormat = new SimpleDateFormat(DEFAULT_DATE);
        } else if (message.contains(":")) {
            dateFormat = new SimpleDateFormat(DEFAULT_TIME);
        }
        assert dateFormat != null;
        return dateFormat.parse(message);
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个java.util.Date 类型的对象
     */
    public static Date parseStringToUtilDate(String message, String pattern) throws ParseException {
        Objects.requireNonNull(message, "传入的内容不能是null");
        Objects.requireNonNull(pattern, "传入的内容不能是null");
        DateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.parse(message);
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 ZonedDateTime 类型的对象
     */
    public static ZonedDateTime parseStringToZonedDateTime(String message) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        return ZonedDateTime.parse(message, AFTER_8_FORMAT);
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 ZonedDateTime 类型的对象
     */
    public static ZonedDateTime parseStringToZonedDateTime(String message, String pattern) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        Objects.requireNonNull(pattern, "传入的内容不能是null");
        return ZonedDateTime.parse(message, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 OffsetDateTime 类型的对象
     */
    public static OffsetDateTime parseStringToOffsetDateTime(String message) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        return OffsetDateTime.parse(message, AFTER_8_FORMAT);
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 OffsetDateTime 类型的对象
     */
    public static OffsetDateTime parseStringToOffsetDateTime(String message, String pattern) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        Objects.requireNonNull(pattern, "传入的内容不能是null");
        return OffsetDateTime.parse(message, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 LocalTime 类型的对象
     */
    public static LocalTime parseStringToLocalTime(String message) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        return LocalTime.parse(message, DateTimeFormatter.ofPattern(DEFAULT_TIME));
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 LocalTime 类型的对象
     */
    public static LocalTime parseStringToLocalTime(String message, String pattern) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        Objects.requireNonNull(pattern, "传入的内容不能是null");
        return LocalTime.parse(message, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 LocalDate 类型的对象
     */
    public static LocalDate parseStringToLocalDate(String message) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        return LocalDate.parse(message, DateTimeFormatter.ofPattern(DEFAULT_DATE));
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 LocalDate 类型的对象
     */
    public static LocalDate parseStringToLocalDate(String message, String pattern) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        Objects.requireNonNull(pattern, "传入的内容不能是null");
        return LocalDate.parse(message, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 LocalDateTime 类型的对象
     */
    public static LocalDateTime parseStringToLocalDateTime(String message) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        return LocalDateTime.parse(message, AFTER_8_FORMAT);
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 LocalDateTime 类型的对象
     */
    public static LocalDateTime parseStringToLocalDateTime(String message, String pattern) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        Objects.requireNonNull(pattern, "传入的内容不能是null");
        return LocalDateTime.parse(message, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 OffsetTime 类型的对象
     */
    public static OffsetTime parseStringToOffsetTime(String message) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        return OffsetTime.parse(message, DateTimeFormatter.ofPattern(DEFAULT_TIME));
    }

    /**
     * 传入一个字符串，按照默认的格式进行解析，返回一个 OffsetTime 类型的对象
     */
    public static OffsetTime parseStringToOffsetTime(String message, String pattern) {
        Objects.requireNonNull(message, "传入的内容不能是null");
        Objects.requireNonNull(pattern, "传入的内容不能是null");
        return OffsetTime.parse(message, DateTimeFormatter.ofPattern(pattern));
    }
}
